package com.yangrd.airship.generator.page.impl.factory.clazz;

import com.yangrd.airship.generator.page.*;
import com.yangrd.airship.generator.page.enhance.TranslateHelper;
import com.yangrd.airship.generator.page.impl.factory.clazz.annotation.CGAction;
import com.yangrd.airship.generator.page.impl.factory.clazz.annotation.CGColumn;
import com.yangrd.airship.generator.page.impl.factory.clazz.annotation.CGQueryCriteria;
import com.yangrd.airship.generator.support.utils.ObjMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.reflect.FieldUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yangrd
 * @date 2021/11/26
 */
@RequiredArgsConstructor
public class ClassPageGeneratorDefineFactory implements PageGeneratorDefineFactory<Class<?>> {

    private final TranslateHelper translateHelper;

    @Override
    public PageGeneratorDefine create(Class<?> dClass) {
        List<PageColumn> pageColumns = listCol(dClass);
        List<PageQueryCriteria> pageQueryCriteria = listQueryCriteria(dClass);
        List<PageAction> pageActions = listAction(dClass);
        return PageGeneratorDefine.of(
                dClass.getSimpleName(),
                pageQueryCriteria,
                pageColumns,
                pageActions
        );
    }



    private List<PageQueryCriteria> listQueryCriteria(Class<?> dClass) {
        List<Field> fields = FieldUtils.getFieldsListWithAnnotation(dClass, CGQueryCriteria.class);
        return ObjMapper.mapList(fields, field -> PageQueryCriteria.of(
                field.getName(),
                field.getAnnotation(CGQueryCriteria.class).value(),
                null
        ));
    }

    private List<PageColumn> listCol(Class<?> dClass) {
        List<Field> allFieldsList = FieldUtils.getAllFieldsList(dClass);
        return ObjMapper.mapList(allFieldsList, field -> {
            CGColumn column = field.getAnnotation(CGColumn.class);

            Boolean show = Objects.isNull(column) || column.show();

            String title = Objects.nonNull(column) ? column.title() : translateHelper.translateCn(field.getName());

            PageColumn.FetchType fetchType = Objects.nonNull(column) ? column.fetchType() : PageColumn.FetchType.SELF;
            return PageColumn.of(
                    field.getName(),
                    field.getType(),
                    show,
                    title,
                    fetchType
            );
        });
    }

    private List<PageAction> listAction(Class<?> dClass) {
        CGAction[] cgActions = dClass.getAnnotationsByType(CGAction.class);
        return ObjMapper.mapList(cgActions, cgAction -> {
            Set<String> tempCols = new HashSet<>(Arrays.asList(cgAction.columns()));
            List<String> allCols = ObjMapper.mapList(FieldUtils.getAllFieldsList(dClass), Field::getName);
            List<String> columns = tempCols.stream().anyMatch(o -> o.equals("*")) ? allCols : allCols.stream().filter(tempCols::contains).collect(Collectors.toList());
            if(cgAction.excludes().length==0){
                return PageAction.of(cgAction.value(), columns);
            }else{
                Set<String> excludes = new HashSet<>(Arrays.asList(cgAction.excludes()));
                List<String> cols = columns.stream().filter(o -> !excludes.contains(o)).collect(Collectors.toList());
                return PageAction.of(cgAction.value(), cols);
            }
        });
    }
}
